/**
 * @Copyright (c) 2005,闲情网站
 * @All rights reserved.
 *
 * Ajax 应用类
 *
 * @file_name   DAjax.js
 * @version     2.0
 * @author      黄新泽
 * @create      2005-05-06
 * @update      2007-09-27 14:45:42
 */

/**
 *  var logic = {id:"user_data", act:"findUserRp",  typ:"o", cla:"UserRp:username", operateType:"class", cache:0};
 *  var ctl = ['username', 'pass'];
 *
 *  var map_info = new DAjax("/index.php?ctl=map", {option:{messageState:false, message:"地图加载中..."}, logic:logic, queryKey:{}, setResponseKey:ctl});
 *
 */


var DAjax = Class.create({
    className : 'DAjax',
    lbType : 'n',
    debug  : true,
    max  : 1,
    request:{num:0, maxIndex:0, indexRow:[]},

    /**
     * 构造函数
     *
     * @param Object url          ajax request url/msg
     * @param Object option       option
     * @param Object requestLogic contain 'id act type'
     * @param Array  queryKey     query key
     * @param ArrayObject         setResponseKey  ctl set key
     *
     * TODO:更改后为option:{option, requestLogic, queryKey, setResponseKey}
     * @access  public 
     */
    initialize : function(url, option) 
    {
        this.url                = null;

		this.form = {formName: null, method:"get", messageState:true, message:L_Global.DAjax['message'], page:null, lbType:"n", cache:false},
		this.logic = {id: '0', typ:"o",  data_type:'pack'};
		this.queryKey = {};  //数组，传递给后台的要查询的字段，
		this.setResponseKey = {}; ////数组或者是关联数组，得到返回的数据后，要设置数据的客户端控件
		this.onSend = function(){this.sendRequestMark = true; return true;}; //发送前和的方法，比如把按钮隐藏起来
		this.onGet = function(){};  //得到数据后执行的方法,不管是否为正确数据!
		this.onSuccess = function(responseText){if (!$(this.eTarget)){
                if ('mask' == this.form.messageState)
                {
                    box.msg(responseText, this.lbType);
                }
                else
                {
                    box.msg(responseText, this.lbType);
                }
            }
        };  //设置数据后执行的方法

		this.onError = function(){};

        this.url    = url;

		Object.extend(this.form, option.form || { });
		Object.extend(this.logic, option.logic || { });
		Object.extend(this.queryKey, option.queryKey || { });
		Object.extend(this.setResponseKey, option.setResponseKey || { });
		Object.extend(this.onSend, option.onSend || { });
		Object.extend(this.onGet, option.onGet || { });
		Object.extend(this.onSuccess, option.onSuccess || { });
		Object.extend(this.onError, option.onError || { });

		if ($(this.logic.id))
		{
			this.logic.id = this.logic.id + '';
		}
		else
		{
			this.request['maxIndex'] ++;
			this.request['maxIndex']  = this.request['maxIndex'] + '';
			this.logic.id = this.request['maxIndex'];
		}

		this.request['indexRow'].push(this.logic.id);

        this.queryString = $H(this.logic).toQueryString() + '&' + $H(this.queryKey).toQueryString();
        this.eTarget     = this.logic.id;

        //关联数组，多记录，要传送的查询的数据,数据要在真正查询的时候才能被正确设置
        this.queryData              = {}                        ;   
        this.responseRows           = 0                         ;   //返回查询数据的行数
        this.error                  = 0                         ;   //返回是否有误

        this.lbType = this.form.lbType;

        this.setResponseRowKey      = new Array()               ;   //数组或者是关联数组，得到返回的数据后，要设置表格数据的客户端控件

        this.onSend                 = this.onSend;
        this.onGet                  = this.onGet;
        this.onSuccess              = this.onSuccess;
        this.onError                = this.onError;


        this.collectCarbage         = function(){
            if (Prototype.Browser.IE)
            {
                CollectGarbage(); 
                setTimeout("CollectGarbage();", 1000);
            }
        };  

        //初始化提示消息类
        //this.messageId              = this.logic.id; //提示消息ID
        this.msg                    = new Message(this.logic.id, this.form.message, this.form.messageState);
        
        if(this.isTrue(this.form.page))
        {
            this.page = new Page(this.form.page);
        }

        //Cache
        if(use_cache && 'undefined'!=typeof(Cache) && this.logic.cache)
        {
            this.cache = new Cache(this.logic.id, this.logic.cache);
        }
        else
        {
            this.cache = null;
        }

        url    = null; 
        option = null; 
    },
    
    remove : function()
    {
        this.cache = null;
        this.page = null;
        this.msg  = null;
        this.setResponseRowKey = null;
        this.form = null;
    },

    /**
     * 完成状态方法
     *
     * @param Object    transport   ajax response object
     *
     * @access  public
     */
    complete : function(transport)
    {
        if (transport.readyState == 4) 
        {
            this.request.num--;

            var status = 0;

            try
            {
                status = transport.status;
            }
            catch(e)
            {
            }

            if (200 != status) 
            {
                if (this.debug)
                {
                    if (status > 10000 || !status)
                    {
                        //box.showMsgBox('与服务器通信超时, 请重试! ' + status + ' <br />\n', true);
                    }
                    else if (status == 499)
                    {
                        box.showMsgBox(_('kaspersky'));
                    }
                    else if (status < 400)
                    {
                        
                    }
                    else
                    {
                        if (transport.responseText)
                        {
                            try
                            {
                                box.remove();
                            }
                            catch (e) { };

                            box.m('<div class="tips" style="width:500px;">' + transport.responseText + '</div>\n');
                        }
                        else
                        {
                            box.m('<div class="tips" style="width:500px;">' + _('timeout') + status + '</div>\n');
                        }

                        //transport.responseText.stripTags()
                    }
                    
                }
                
                this.msg.failure();
            }

            status = null;
        }

        transport = null;
    },
    

    /**
     * 异常处理
     *
     * @param Object    transport   ajax response object
     *
     * @access  public
     */
    exception : function(transport, e)
    {
        /*
        var line = 0;

        if (Prototype.Browser.IE)
        {
            line = ' 错误类型 : ' + (e.number & 0xFFFF); 
        }
        else
        {
            line = ' 错误行数 : ' + e.lineNumber;
        }

        box.showMsgBox( '发生异常错误, 请将如下内容发送给我们, 谢谢! <br />' + transport.body + '<br />\n 错误位置 : ' + currentTabId + '<br />\n' + line + '<br />\n 错误消息 : ' + e.message , true);

        this.msg.failure();
        */

        transport = null;
        e = null;
    },

    /**
     * 接收数据句柄
     *
     * @param Object    transport   ajax.response object == Ajax.Response, 不是XMLHTTP对象本身
     *
     * @access  public
     */
    receiveData : function(transport)
    {
        try
        {
            //Element.hide('tooltip_singleton');
        }
        catch(e)
        {
        }

        var status = 0;

        try
        {
            status = transport.status;
        }
        catch(e)
        {
        }

        if (200 == status) 
        {
			var response_text = '';

			//var byteArray = _ie ? toByteArrayIE(this.responseData) : toByteArray(this.responseData);
			//var data = msgpackunpack(byteArray);
			//console.info(data)

			if ('pack' == this.logic.data_type)
			{
				if (Prototype.Browser.IE)
				{
					response_text = msgpackunpack(toByteArrayIE(transport.transport)); //传入原始的xmlhttp对象
				}
				else
				{
					response_text = msgpackunpack(toByteArray(transport.responseText));	
				}
			
			}
			else if ('amf' == this.logic.data_type)
			{
				if (transport.responseBody != undefined)
				{
					var a = BinaryToArray(transport.responseBody).toArray();
					for (var i = 0; i < a.length; i++)
					{
						response_text += String.fromCharCode(a[i]);
					}
				}
				else
				{
					response_text = transport.responseText;
				}
				console.info(decodeAMF(response_text))

				console.info(decodeAMF(response_text).message);
				//console.info(decodeAMF(response_text).messages[0].body);
				//response_text = transport.responseText;	
			}
			else
			{
				response_text = transport.responseText;	
			}

            //增加扩展性...... demo  arg 可以通过一个变量来传递,parameters 后来合并,变可以完全兼容
            if (isSet(this.form.onSuccess))
            {
                this.form.onSuccess(response_text, this);
            }
            else
            {
                this.setResponseData(response_text, this); 
            }

            //Cache
            if(this.cache)
            {
                //this.cache.updateCache(this.cache.key, transport);
                if (db)
                {
                    var t = intVal(new Date().getTime()/1000);
                    db.execute('insert into sitrep values (?, ?, ?, ?, ?)', [this.cache.key, response_text, new Date().toJSON(), t, t+this.cache.lifeTime]);
                    t = null;
                }
                else
                {
                    if (!this.cache.getCache(this.cache.key))
                    {
                        this.cache.updateCache(this.cache.key, response_text);
                    }
                }
            }

			response_text = null;
        }

        transport = null;
        return false;
    },

    /**
     * 接收数据句柄
     *
     * @param Object    transport   ajax response object
     *
     * @access  public
     */
    setReceiveData : function(responseText)
    {
        //增加扩展性...... demo  arg 可以通过一个变量来传递,parameters 后来合并,变可以完全兼容
        if (isSet(this.form.onSuccess))
        {
            this.form.onSuccess(responseText, this);
        }
        else
        {
            this.setResponseData(responseText, this);   
        }

        return false;
    },

    /**
     * 响应方法, 设置各种数据
     *
     * @param Object    transport   ajax response object
     *
     * @access  public
     */
    setResponseData : function(responseText, self) 
    {
        //这里要执行onGet事件
        this.onGet()   ;

        //直接返回HTML数据,这样屏蔽了下面的处理数据,返回格式简单
        if ("e" == this.logic.typ)
        {
            this.responseData = responseText;

            if ($(this.eTarget))
            {
                try
                {
                    $(this.eTarget).edit(responseText);

                    if('undefined'!=typeof(Element.lazyload)  && $(this.eTarget))
                    {
                        //$$('#' + this.eTarget + ' img').invoke('lazyload');
                    }           
                }
                catch(e)
                {
                }
            }
            else
            {
            }

            if (true)
            {
                this.onSuccess(responseText);
            }
            else
            {
                this.onError();
            }

            if (Prototype.Browser.IE && !Prototype.Browser.IE7) // && !Prototype.Browser.IE7
            {
            }
        }
        else
        {
            var data = null;

            try
            {
				if (Object.isString(responseText))
				{
					data = responseText.evalJSON();
				}
				else
				{
					data = responseText;
				}
            }
            catch(e)
            {
                this.responseMessageData    = {num:0, error:1}  ; 
                this.responseRows           = 0;
                this.error                  = 1;
                this.responseData           = {}; 
                this.rMsg                   = responseText

                this.onError();

                /*
                if (this.form.messageState)
                {
                    if (responseText.blank())
                    {
                        responseText = '发生错误!';
                    }

                    box.showMsgBox(responseText);
                    this.msg.removeMessage();
                }
                */
            }

            if (data)
            {
                this.responseMessageData    = data['head'] || {num:0, error:1}   ; 
                this.responseRows           = parseInt(this.responseMessageData.num);
                this.error                  = this.responseMessageData.error && parseInt(this.responseMessageData.error);
                this.responseData           = data['body'] ? data['body'] : {}; 

                this.rMsg                   =   this.responseMessageData.message;

                //firebug 信息
                if ('undefined' != typeof(data['debug']))
                {
                    console.debug(data['debug']);
                }

                if(this.isTrue(this.error))
                {
                    this.errorMessage = this.responseMessageData.message;
                    //这里执行onError
                    
                    //this.msg.failure();
                    this.onError();
                    data = null;
                }
                else
                {
                    //检测是否需要自动设置客户端控件, 暂时只处理一行的
                    if(this.isTrue(this.setResponseKey))
                    {
                        var i, ctlName, fldName;

                        //如果是数组，而不是关联数组
                        if (window.Array == this.setResponseKey.constructor)
                        {
                            var l = this.setResponseKey.length;
                            for (i=0; i<l; i++)
                            {
                                ctlName = this.setResponseKey[i] ;
                                fldName = ctlName ;
                                
                                this.setResponseCtl(ctlName, fldName);
                            }//end for
                        }
                        else if(window.Object == this.setResponseKey.constructor)
                        {
                            for (i in this.setResponseKey )
                            {
                                ctlName = i ;
                                fldName = this.setResponseKey[i]  ;
                                
                                this.setResponseCtl(ctlName, fldName);
                            }//end for

                        }
                        else
                        {
                            alert('setResponseKey Wrong!');
                        }
                    }

                    //执行onSuccess
                    this.onSuccess(data);
                }
            }

            this.responseMessageData     = null;
            this.responseRows            = null;
            this.error                   = null;
            this.rMsg                    = null;

            data = null;
        }

        //如果为了调试数据， 下面三行可以不设置NULL
        this.responseData = null;
        responseText = null;
        transport = null;

        this.msg.removeMessage();
        this.collectCarbage();
        return;
    },

    /**
     * 设置控件数据
     *
     * @param String    ctlName control name 
     * @param String    fldName control value: always is db field name 
     *
     * @access  public
     */
    setResponseCtl : function(ctlName, fldName)
    {
        //存放某个控件对象
        var key_data = this.responseData['head'] ;
        if(!$(ctlName))
        {
            //alert("无法找到控件 : " + ctlName);
            return  false;
        }

        try 
        {
            if(typeof(key_data[fldName]) === "undefined")
            {
                alert("无法取得该字段的数据:"+fldName);
                return  false;
            }
            else
            {
                $(ctlName).value = key_data[fldName]; 
            }

        }
        catch(e)
        {
            alert(e.message);
        }

        key_data = null
    },

    /**
     * 序列化表单数据
     *
     * @return  String  Serialize data
     *
     * @access  public
     */
    formSerialize : function()
    {
        return this.form.formName ? '&' + Form.serialize(this.form.formName) : '';
    },

    /**
     * 发送Ajax请求 == sendRequest
     *
     * @param   Object  q   query data
     *
     * @access  public
     */
    send : function(ctl, q) 
    {
        this.sendRequest(ctl, q);
    },

    /**
     * 发送Ajax请求
     *
     * @param   Object  q   query data
     *
     * @access  public
     */
    sendRequest : function(ctl, q) 
    {
        //如果一段时间后用户没有操作页面,则停止发送ajax请求
        if ('undefined' != typeof(active))
        {
            if (!active)
            {
                return false;
            }
        }

		if (this.msg.loadCount >= this.max)
		{
			return false;
		}

        //cache不支持并发处理,解决办法,传回key值.用到较少,不做处理
        //为了cache考虑,禁止统一操作并发请求
        if (this.cache && this.msg.loadCount)
        {
            //alert(this.msg.loadMessage + "\n 请稍候再次读取!");
            return false;
        }

        if (this.request.num >= 9)
        {
            console.info('发送请求太多.');
            return ;
        }

        //执行onSend事件
        this.onSend();

        var tQS = this.queryString;
        tQS += this.formSerialize();

        if (this.isSet(ctl))
        {
            ctl.each(function(s) 
                    {
                        if(!$(s))
                        {
                            //alert("无法找到控件 : " + s);
                        }
                        else
                        {
                            tQS += "&" + Form.Element.serialize(s);
                        }
                    });
        }

        if (this.isSet(q))
        {
            tQS += '&' + $H(q).toQueryString();
        }
        
        var qDS = $H(this.queryData).toQueryString();
        tQS += qDS ? '&' + qDS : '';

        if(!this.sendRequestMark)
        {
            return false;
        }

        //Cache，应该如入cache类中统一处理，目前db暂时放在这儿了！
        if(this.cache)
        {
            this.cache.key = tQS.replace(/[^a-zA-Z0-9]/gi,"").md5();

            if (db)
            {
                var rs = db.execute('select * from sitrep where hash_id="' + this.cache.key + '" order by hash_date desc');
                console.info('select * from sitrep where hash_id="' + this.cache.key + '" order by hash_date desc');

                while (rs.isValidRow()) 
                {
                    //alert(rs.field(0) + '@' + rs.field(1));
                    this.setReceiveData(rs.field(1));

                    rs.close();
                    rs = null;

                    return false;
                }

                rs.close();
                rs = null;
            }
            else
            {
                if (this.cache.getCache(this.cache.key))
                {
                    this.setReceiveData(this.cache.getCache(this.cache.key));
                    return false;
                }
            }
        }

        //设置随机数
        var s = this.rand();
        tQS += '&r=' + s ;

        this.msg.showMessage();
        this.request.num++;

		var overrideMimeType = null;
		var overrideHeaders = null;

		if ('pack' == this.logic.data_type)
		{
			var overrideMimeType = "text/plain; charset=x-user-defined";
			var overrideHeaders = ["Accept-Charset", "x-user-defined"];
		}

        var ajaxObj = new Ajax.Request(
                                        this.url,
                                        {
                                            method          : this.form.method,
                                            requestHeaders  : ["Cache-Control","no-cache"],
                                            overrideMimeType  : overrideMimeType,
                                            overrideHeaders  : overrideHeaders,
                                            parameters      : tQS,

                                            onSuccess       : this.receiveData.bind(this),
                                            onComplete      : this.complete.bind(this),
                                            onException     : this.exception.bind(this)
                                        }
                                    );
                                    
        if ('e' == this.logic.typ)
        {
        }
        else
        {
        }
        
        ctl = null;
        q   = null;
        qDS = null;
        s   = null;
        tQS = null;
        ajaxObj = null;
    },

    /**
     * 随机数  public function  暂时放在这儿,跟随此类到处跑
     *
     * @return  Int num rand number
     *
     * @access  public
     */
    rand : function()
    {
        return Math.random();
    },

    /**
     * isSet -> from PHP  function  public function  暂时放在这儿,跟随此类到处跑
     *
     * @return  Mixed   arg Arg need be checked
     *
     * @access  public
     */
    isSet : function(arg)
    {
        return 'undefined' != typeof(arg) ? true : false;
    },

    /**
     * function  public function  暂时放在这儿,跟随此类到处跑
     *
     * @return  Mixed   arg Arg need be checked
     *
     * @access  public
     */
    isTrue : function(v)
    {
        return (v==true 
            || ("number"==typeof(v) && 0!=v) 
            || ("string"==typeof(v) && ""!=v  && "0"!=v && "off"!=v && "no"!=v) 
            || ("object"==typeof(v) && null!=v && {}!=v && []!=v) 
            );
    },

    /**
     * 删除最后一个key缓存
     *
     * @access  public
     */
    delCache : function()
    {
        if(this.cache)
        {
            this.cache.delCache(this.cache.key);
        }

    },

    /**
     * 删除此Ajax下的全部缓存
     *
     * @access  public
     */
    delCacheAll : function()
    {
        if(this.cache)
        {
            this.cache.delCacheAll();
        }
    }
});
